/**
 * 
 */
package com.projetosi.web.server.sistema.objetos;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.projetosi.web.server.sistema.sistema.RepositorioDeDados;
import com.projetosi.web.server.sistema.util.ConversorDeCoordenadas;

/**
 * @author filipealencar_
 * Classe que implementa o caso de uso 20 , ou seja , localiza usuarios por 
 * sua proximidade geografica atraves da api do google maps geocode
 */
public class LocalizadorDeUsuario {
	final private String enderecoGoogleAPI = "http://maps.google.com/maps/api/geocode/json?address=";
	private final Double COEFICIENTE_DE_APROXIMACAO = 0.0001;
	/**
	 * Metodo que ordena a lista de amigos do usuario por proximidade geografica
	 * @param user - Usuario que tera sua lista de amigos ordenados	
	 * @return - Uma string formatada com os usuarios ordenados 
	 * @throws Exception
	 */
	public String localizarUsuario(Usuario user) throws Exception{
		Double latitudeUsuario = Double.parseDouble(obterCoordenadas(user.getEndereco())[0]);
		Double longitudeUsuario = Double.parseDouble(obterCoordenadas(user.getEndereco())[1]);
		Map<Double, Usuario > mapa = new TreeMap<Double, Usuario>();
		List<Usuario> todosUsuarios = RepositorioDeDados.getInstance().getUsuarios();
		List<Usuario> outrosUsuarios = new ArrayList<Usuario>();
		outrosUsuarios.addAll(todosUsuarios);
		outrosUsuarios.remove(user); // nao deve conter o usuario que requisitou a localizacao dos usuarios.
		for(Usuario usuario: outrosUsuarios){
			String[] coordAmigo = obterCoordenadas(usuario.getEndereco());
			ConversorDeCoordenadas DistanciaCoordenada = new ConversorDeCoordenadas();
			Double distancia = DistanciaCoordenada.geoDistanceInKm(latitudeUsuario, longitudeUsuario,
					Double.parseDouble(coordAmigo[0]), Double.parseDouble(coordAmigo[1]));
			while(mapa.containsKey(distancia)){
				distancia = distancia + COEFICIENTE_DE_APROXIMACAO;
			}
			mapa.put(distancia,usuario);
		}
		return mapaString(mapa);
	}

	/**
	 * Retorna uma representacao em string dos usuarios e seus respectivos enderecos
	 * @param mapa O mapa que a distancia entre um certo usuario e todos os demais usuarios do sistema
	 * @return Uma string contendo o nome dos usuarios e seus respectivos endereços.
	 */
	private String mapaString(Map<Double, Usuario> mapa) {
		ArrayList<Usuario> listaUsuarios = new ArrayList<Usuario>();
		for(Usuario user1: mapa.values()){
			listaUsuarios.add(user1);
		}
		String str="";
		for(Usuario user : listaUsuarios){
			str+= user.getNome()+ " - " + user.getEndereco()+"; ";
		}
		return str.substring(0,str.length()-2);
	}

	/**
	 * Retorna as coordenadas(latitude e longitude) de um endereço especificado.
	 * @param endereco O endereco que deve ter as coordenadas obtidas.
	 * @return Um array de string contendo as respectivas coordenadas.
	 * @throws IOException
	 * @throws MalformedURLException
	 */
	private String[] obterCoordenadas(String endereco) throws IOException, MalformedURLException {
		endereco = endereco.replaceAll(" ", "+");
		URLConnection con = new URL(enderecoGoogleAPI + endereco + "&sensor=false").openConnection();
		con.connect();
		BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
		String inputLine="";
		StringBuffer resultado = new StringBuffer();
		while (null != ((inputLine = br.readLine()))) {  
			resultado.append(inputLine);
		}
		br.close();
		String[] listaResultado = formatarString(resultado);
		return listaResultado;
	}

	/**
	 * Formata a string a fim de obter apenas certa parte dela.
	 * @param resultado A string a ser formatada
	 * @return A string formatada
	 */
	private String[] formatarString(StringBuffer resultado) {
		String resultado1 = resultado.toString().substring(resultado.toString().lastIndexOf("lat") - 3);
		String[] listaResultado = resultado1.split(" ");
		StringBuffer str = new StringBuffer();
		for (int index = 0; index < listaResultado.length; index++){
			if(listaResultado[index].equals(":")){
				try{
					str.append(listaResultado[index + 1]);
				}
				catch(Exception e){
				}
			}
		}
		listaResultado = str.substring(0, str.length() - 6).split(",");
		return listaResultado;
	}
	
}